<?php

namespace services\member;

use common\models\api\AccessToken;
use common\models\clinic\TreatmentRoom;
use common\models\rbac\UserRoom;
use services\api\AccessTokenService;
use services\common\CommonService;
use Yii;
use common\components\Service;
use common\helpers\CommonHelper;
use common\models\member\Member;
use common\models\member\Attr;
use common\models\rbac\Action;
use common\models\rbac\Menu;
use common\models\rbac\Module;
use common\models\rbac\Role;
use common\models\rbac\RolePermission;
use common\models\rbac\UserRole;
use common\models\rbac\Department;
use common\models\patient\User;
use common\models\clinic\Clinic;
use common\models\base\Project;
use common\models\base\Profession;
use api\modules\v1\forms\member\MemberForm;
use api\modules\v1\forms\dingtalk\DingtalkForm;
use yii\data\Pagination;
use yii\db\Expression;

/**
 * Class MemberService
 * @package services\member
 *
 */
class MemberService extends Service
{
    /**
     * 用户
     *
     * @var Member
     */
    protected $member;

    /**
     * 根据ID查找信息
     *
     * @param int $id
     * @return Member|null
     */
    public function findById(int $id = 0): ?Member
    {
        return Member::find()->where(['id' => $id])->one();
    }

    /**
     * 查找信息
     *
     * @param array $condition
     * @return Member|null
     */
    public function findInfo(array $condition = []): ?Member
    {
        $query = Member::find();

        isset($condition['mobile']) && $query->andWhere(['mobile' => $condition['mobile']]);
        isset($condition['ding_unionid']) && $query->andWhere(['ding_unionid' => $condition['ding_unionid']]);

        return $query->one();
    }

    /**
     * 获取用户信息
     *
     * @param array $condition
     * @param int $isArray 是否返回数组【1是、0否】
     * @return array|\yii\db\ActiveRecord|null
     */
    public function getInfo(array $condition = [], $isArray = 1)
    {
        $query = Member::find();

        isset($condition['id']) && $query->andWhere(['id' => $condition['id']]);
        isset($condition['mobile']) && $query->andWhere(['mobile' => $condition['mobile']]);
        isset($condition['status']) && $query->andWhere(['status' => $condition['status']]);

        if ($isArray === 1) {
            $query->asArray();
        }

        return $query->one();
    }

    /**
     * 用户列表
     *
     * @param array $condition
     * @return array|\yii\db\ActiveRecord[]
     */
    public function findList(array $condition = [])
    {
        $query = Member::find();

        // select
        isset($condition['select']) && $query->select($condition['select']);

        // condition
        isset($condition['id']) && $query->andWhere(['id' => $condition['id']]);
        isset($condition['status']) && $query->andWhere(['status' => $condition['status']]);

        isset($condition['indexBy']) && $query->indexBy($condition['indexBy']);

        return $query->asArray()->all();
    }

    /**
     * 顾问id和姓名列表格式化
     * @param $data
     * @return array
     * @author chenyuebin
     */
    public function findListFormat($data)
    {
        $row = [];
        foreach ($data as $value) {
            $row[] = [
                'id' => $value['id'],
                'name' => $value['realname']
            ];
        }

        return $row;
    }

    /**
     * 关联会员属性
     *
     * @param array $condition
     * @return array|\yii\db\ActiveRecord[]
     */
    public function findListInnerAttr(array $condition = [])
    {
        $query = Member::find()->alias('a')->select(['a.*', 'b.is_department_leader', 'b.clinic_id'])
            ->innerJoin(Attr::tableName() . ' AS b', 'b.member_id = a.id AND b.project_id = ' . $condition['project_id']);

        if (isset($condition['department_id']) && $condition['department_id']) {
            $query->andWhere(['b.department_id' => $condition['department_id']]);
        }
        if (isset($condition['member_id']) && $condition['member_id']) {
            $query->andWhere(['a.id' => $condition['member_id']]);
        }

        if (isset($condition['status'])) {
            $query->andWhere(['a.status' => $condition['status']]);
        }

        return $query->asArray()->all();
    }

    /**
     * 格式化会员属性
     *
     * @param array $data
     * @return array
     */
    public function findListInnerAttrFormat(array $data = [])
    {
        $leader_id = [];
        $list = [];
        foreach ($data as $row) {
            $list[] = [
                'id' => $row['id'],
                'realname' => $row['realname'],
                'is_department_leader' => $row['is_department_leader'],
            ];

            if ($row['is_department_leader'] == Attr::IS_DEPARTMENT_LEADER_YES) {
                $leader_id[] = $row['id'];
            }
        }

        return [
            'leader_ids' => $leader_id,
            'list' => $list,
        ];
    }

    /**
     * @param Member $member
     */
    public function lastLogin(Member $member)
    {
        // 记录访问次数
        $member->visit_count += 1;
        $member->last_time = time();
        $member->last_ip = Yii::$app->request->getUserIP();
        $member->save();
    }

    /**
     * 获取用户权限
     *
     * @param $memberId int 用户ID
     * @param $isSuper int 是否超管【0否、1是】
     * @param $projectId int 项目ID
     * @return array [
     *      'module' => [],// 模块
     *      'sider' => [],// 菜单
     *      'action' => [],// 动作
     * ]
     */
    public function getPermissionsList(int $memberId, int $isSuper = 0, int $projectId = 0)
    {
        $return = [
            'header' => [],
            'sider' => [],
            'action' => []
        ];

        if (empty($memberId)) {
            return $return;
        }

        $attr = Yii::$app->services->attr->findInfo([
            'member_id' => $memberId,
            'project_id' => $projectId,
        ]);

        if ($isSuper == Member::IS_SUPER_YES
//            || ($attr && $attr->is_department_leader == Attr::IS_DEPARTMENT_LEADER_PROJECT)
        ) {// 超管or项目管理员
            $menuList = Yii::$app->services->menu->findList([
                'status' => Menu::STATUS_ENABLE,
                'orderBy' => ['sort' => SORT_ASC, 'id' => SORT_ASC],
            ]);

            $actionList = Yii::$app->services->action->findList(['status' => Action::STATUS_ENABLE]);

            $moduleList = Yii::$app->services->module->findList([
                'status' => Module::STATUS_ENABLE
            ]);
        } else {
            // 获取用户绑定角色
            $userRoleList = Yii::$app->services->userRole->findList(['member_id' => $memberId]);
            $roleIds = array_column($userRoleList, 'role_id');

            $menuList = Yii::$app->services->rolePermission->getMenuList($roleIds, $projectId);
            $actionList = Yii::$app->services->rolePermission->getActionList($roleIds, $projectId);
            $moduleList = Yii::$app->services->rolePermission->getModuleList($roleIds, $projectId);
        }

        // 菜单列表
        $return['sider'] = Yii::$app->services->rolePermission->menuListFormat($menuList, 0, $isSuper);

        // 动作列表
        $return['action'] = Yii::$app->services->rolePermission->actionListFormat($actionList);

        // 模块列表
        $return['header'] = Yii::$app->services->rolePermission->moduleListFormat($moduleList);

        return $return;
    }

    /**
     * 格式化用户绑定项目
     *
     * @param array $data
     * @return array
     */
    public function projectListFormat(array $data)
    {
        $list = [];
        foreach ($data as $row) {
            $list[] = [
                'project_id' => $row['id'],
                'name' => $row['name'],
            ];
        }

        return $list;
    }

    /**
     * 验证权限
     *
     * @param Member $member 用户信息
     * @param string $route 路由
     * @param string $projectId 项目ID
     * @return bool
     */
    public function checkAccess(Member $member, string $route = '', int $projectId = 0)
    {
        // 超管无需验证
        if ($member['is_super'] == Member::IS_SUPER_YES) {
            return true;
        }

        // 权限信息
        $action = Yii::$app->services->action->findInfo([
            'status' => Action::STATUS_ENABLE,
            'flag' => $route,
        ]);

        if ($action) {
            if ($projectId == 0) {
                return false;
            }

            // 项目负责人【跳过】
            $attr = Yii::$app->services->attr->findInfo([
                'member_id' => $member['id'],
                'project_id' => $projectId,
            ]);
            if ($attr && $attr->is_department_leader == Attr::IS_DEPARTMENT_LEADER_PROJECT) {
                return true;
            }

            // 获取用户绑定角色
            $userRoleList = Yii::$app->services->userRole->findList(['member_id' => $member['id']]);
            $roleIds = array_column($userRoleList, 'role_id');

            // 是否有权限
            $actionList = Yii::$app->services->rolePermission->getActionList(
                $roleIds,
                $projectId,
                ['permission_id' => $action['id']]
            );

            return $actionList ? true : false;
        }

        return true;
    }

    /**
     * 获取用户权限+所属项目
     *
     * @param int $memberId 用户ID
     * @param int $isSuper 是否超管
     * @param int $projectId 项目ID
     * @return array
     */
    public function memberPerssions(int $memberId = 0, int $isSuper = 0, int $projectId = 0)
    {
        // 1.获取用户项目
        $condition = [
            'status' => Project::STATUS_ENABLE,
            'orderBy' => ['sort' => SORT_ASC, 'id' => SORT_ASC]
        ];
        if ($isSuper == Member::IS_SUPER_NO) {
            $memberAttrList = Yii::$app->services->attr->findList([
                'member_id' => $memberId,
            ]);
            $condition['id'] = array_column($memberAttrList, 'project_id');
        }
        $projectList = Yii::$app->services->project->getList($condition);
        $project = $this->projectListFormat($projectList);

        // 2.获取用户列表权限
        if ($projectId == 0) {
            $defaultProjectId = $project[0]['project_id'] ?? 0;
        } else {
            $defaultProjectId = $projectId;
        }
        $auth = $this->getPermissionsList($memberId, $isSuper, $defaultProjectId);

        // 3.获取用户绑定角色
        $userRoleList = Yii::$app->services->userRole->findList([
            'member_id' => $memberId,
            'project_id' => $defaultProjectId,
            'role_id' => [Role::ID_MEDICAL, Role::ID_CUSTOMER]
        ]);
        $roleIds = array_column($userRoleList, 'role_id');

        $attr = Yii::$app->services->attr->findInfo([
            'member_id' => $memberId,
            'project_id' => $defaultProjectId,
        ]);

        // 绑定护士
        $userRole = Yii::$app->services->userRole->findInfo([
            'member_id' => $memberId,
            'role_id' => Role::ID_NURSE,
        ]);

        return [
            'defaultProjectId' => $defaultProjectId,// 当前项目ID
            'auth' => $auth,// 权限
            'project' => $project,// 项目
            'is_role_kf' => $isSuper || ($attr && $attr->is_department_leader == Attr::IS_DEPARTMENT_LEADER_PROJECT) || in_array(Role::ID_CUSTOMER, $roleIds) ? 1 : 0,
            'is_role_yz' => $isSuper || ($attr && $attr->is_department_leader == Attr::IS_DEPARTMENT_LEADER_PROJECT) || in_array(Role::ID_MEDICAL, $roleIds) ? 1 : 0,
            'is_nurse' => empty($userRole) ? 0 : 1,
        ];
    }

    /**
     * 获取人员
     *
     * @param array $params
     * @return array
     */
    public static function getList(array $params)
    {
        $departmentLeaderId = $params['department_leader_id'];
        $limit = $params['limit'];
        $page = $params['page'];

        $role_project = '';
        if (isset($params['projectId']) && !empty($params['projectId'])) {
            $role_project .= ' and r.project_id = ' . $params['projectId'];
        }

        $query = Member::find()
            ->alias('m')
            ->leftJoin(Attr::tableName() . ' attr', 'm.id = attr.member_id')
            ->leftJoin(UserRole::tableName() . ' r', 'm.id = r.member_id' . $role_project)
            ->leftJoin(Department::tableName() . ' d', 'd.id = attr.department_id')// 此处以单部门考虑
            ->leftJoin(Clinic::tableName() . ' c', 'c.id = attr.clinic_id')
            ->where(['m.is_super' => Member::IS_SUPER_NO])// 确定现在是人员是单个部门
            ->andWhere(['!=', 'm.status', Member::STATUS_DELETE]);
        isset($params['projectId']) && !empty($params['projectId']) && $query->andWhere(['attr.project_id' => $params['projectId']]);
        $query->groupBy('m.id,attr.member_id')
            ->select([
                'c.name as clinic_name', 'c.id as clinic_id', 'm.id', 'm.realname as name',
                'm.username', 'attr.is_department_leader', 'm.mobile', 'd.name as department_name',
                'attr.profession_id', 'attr.profession_name',
                new Expression('FROM_UNIXTIME(m.`created_at`, "%Y-%m-%d") created_at'), 'm.status',
                new Expression('FROM_UNIXTIME(m.`last_time`, "%Y-%m-%d %H:%i") last_time'),
                'group_concat(attr.project_id) as project_id', 'attr.department_id'
            ]);

        // 普通员工为传-1,0和空一样
        if ($departmentLeaderId == -1) {
            $query = $query->andWhere(['attr.is_department_leader' => Attr::IS_DEPARTMENT_LEADER_NO]);
        }
        if ($departmentLeaderId == 2) {
            $query = $query->andWhere(['attr.is_department_leader' => Attr::IS_DEPARTMENT_LEADER_PROJECT]);
        }

        // 岗位
        if (isset($params['profession_id']) && $params['profession_id']) {
            $query = $query->andWhere(['attr.profession_id' => $params['profession_id']]);
        }

        // 部门
        if (isset($params['department_id']) && $params['department_id']) {
            $query = $query->andWhere(['attr.department_id' => $params['department_id']]);
        }

        // 诊室
        if (isset($params['clinic_id']) && $params['clinic_id']) {
            $query = $query->andWhere(['attr.clinic_id' => $params['clinic_id']]);
        }

        // 角色
        if (isset($params['role_id']) && $params['role_id']) {
            $query = $query->andWhere(['r.role_id' => $params['role_id']]);
        }

        // 关键词【姓名or手机号】
        if (isset($params['keyword']) && $params['keyword']) {
            $query = $query->andWhere([
                'or',
                ['like', 'm.realname', $params['keyword']],
                ['=', 'm.mobile', $params['keyword']]
            ]);
        }

        if (!is_null($params['status'])) {
            $query = $query->andWhere(['m.status' => $params['status']]);
        }

        $pagination = new Pagination([
            'defaultPageSize' => $limit,
            'totalCount' => $query->count(),
            'validatePage' => false,
        ]);

        $list = $query
            ->offset($pagination->offset)
            ->limit($pagination->limit)
            ->orderBy(['m.sort' => SORT_ASC, 'm.status' => SORT_DESC, 'm.id' => SORT_DESC])
            ->asArray()
            ->all();

        foreach ($list as &$item) {
            $projectArray = Project::find()->where(['in', 'id', explode(',', $item['project_id'])])->select('id,name')->asArray()->all();
            $project = array_column($projectArray, 'name');
            $project_id = array_column($projectArray, 'id');
            $item['project_id'] = implode(',', $project_id);
            $item['project'] = implode(',', $project);
            $item['role'] = MemberService::getRoleIdByMemberId($item['id'], $params['projectId'] ?? '');
            $item['role_name'] = MemberService::getRoleNameByMemberId($item['id'], $params['projectId'] ?? '');
            $item['department_leader'] = Attr::$departmentLeaderName[$item['is_department_leader']];
            $item['clinic_id'] = $item['clinic_id'] ?: 0;
            $item['clinic_name'] = $item['clinic_name'] ?: '';
            $item['last_time'] == '1970-01-01 08:00' ? $item['last_time'] = '' : '';
        }

        return [
            'page' => (int)$page,
            'pageSize' => (int)$limit,
            'total' => (int)$pagination->totalCount,
            'list' => $list,
        ];
    }

    /**
     * 根据用户id返回角色id
     *
     * @param int $memberId
     * @return array
     */
    public static function getRoleIdByMemberId(int $memberId, $project_id = null)
    {
        $where = ['and'];
        $where[] = ['member_id' => $memberId];

        if (!empty($project_id)) {
            $where[] = ['project_id' => $project_id];
        }
        $roleIdData = UserRole::find()->where($where)->select('role_id')->column();

        return $roleIdData;
    }

    /**
     * 根据用户id返回角色id
     *
     * @param int $memberId
     * @return array
     */
    public static function getRoomIdByMemberId(int $memberId, $project_id = null)
    {
        $where = ['and'];
        $where[] = ['member_id' => $memberId];

        if (!empty($project_id)) {
            $where[] = ['project_id' => $project_id];
        }
        $roomIdData = UserRoom::find()->where($where)->select('room_id')->column();

        return $roomIdData;
    }

    /**
     * 根据员工id获取对应的角色信息
     *
     * @param $memberId
     * @return array
     */
    public static function getRoleNameByMemberId(int $memberId, $project_id = null)
    {
        $where = ['and'];
        $where[] = ['u.member_id' => $memberId];

        if (!empty($project_id)) {
            $where[] = ['u.project_id' => $project_id];
        }
        $roleData = Role::find()
            ->alias('r')
            ->leftJoin(UserRole::tableName() . ' u', 'r.id = u.role_id')
            ->where($where)
            ->select('r.name')
            ->column();

        $str = implode(',', $roleData);
        return $str;
    }


    /**
     * 根据角色id获取对应的角色信息
     *
     * @param array $roleIds
     * @return array
     */
    public static function getRoleName($roleIds)
    {
        $roleData = Role::find()
            ->alias('r')
            ->where(['id' => $roleIds])
            ->select('r.name')
            ->column();

        $str = implode(',', $roleData);
        return $str;
    }

    public static function getRoomName($roomIds)
    {
        $roomData = TreatmentRoom::find()
            ->alias('r')
            ->where(['id' => $roomIds])
            ->select('r.name')
            ->column();

        $str = implode(',', $roomData);
        return $str;
    }

    /**
     * 新增人员，操作三张表， member, member_attr， rbac_user_role
     *
     * @param $data
     * @return array
     * @throws \Exception
     */
    public static function createMember($data)
    {
        $transaction = Yii::$app->db->beginTransaction();
        //   $transaction2 = Yii::$app->db2->beginTransaction();
        try {
            // 1.生成用户
            $memberModel = new Member;
            $memberModel->username = $data['user_name'];
            $memberModel->mobile = $data['mobile'];
            $memberModel->password_hash = $data['password_hash'];
            $memberModel->auth_key = $data['auth_key'];
            $memberModel->realname = $data['name'];
            $memberModel->status = $data['status'];
            $memberModel->gender = $data['gender'];
            if (!$memberModel->save()) {
                throw new \Exception(json_encode($memberModel->errors), 500);
            }

            // 2.生成用户属性

            foreach ($data['project_id'] as $project) {
                $memberAttrModel = new Attr;
                $memberAttrModel->member_id = $memberModel->id;
                $memberAttrModel->project_id = $project;
                self::addProjectCount($project, 1);
                isset($data['professionName']) && !empty($data['professionName']) && $memberAttrModel->profession_name = $data['professionName'];
                isset($data['professionId']) && !empty($data['professionId']) && $memberAttrModel->profession_id = $data['professionId'];
                isset($data['is_department_leader']) && $memberAttrModel->is_department_leader = $data['is_department_leader'];

                if (isset($data['department_id']) && !empty($data['department_id'])) {
                    $memberAttrModel->department_id = $data['department_id'];
                    self::addDepartmentCount($data['department_id'], 1);
                }

                //如果有诊室,更新诊室,同时更新诊室表的用户信息
                if (isset($data['clinic_id']) && !empty($data['clinic_id'])) {
                    $memberAttrModel->clinic_id = (string)$data['clinic_id'];
                    MemberService::addClinic($data['clinic_id'], $data['name']);
                }

                if (!$memberAttrModel->save()) {
                    throw new \Exception($memberAttrModel->errors, 500);
                }
            }

            // 3.角色绑定
            // 获取部门的角色, 操作新怎人员角色
            $operateId = Yii::$app->user->identity['member_id'];

            if (isset($data['role_id']) && !empty($data['role_id'])) {
                foreach ($data['role_id'] as $roleId) {
                    $insertData[] = [
                        'member_id' => $memberModel->id,
                        'role_id' => $roleId,
                        'project_id' => $data['project_id'][0],
                        'operate_id' => $operateId,
                        'created_at' => time(),
                    ];
                }
                Yii::$app->db->createCommand()->batchInsert(UserRole::tableName(), ['member_id', 'role_id', 'project_id', 'operate_id', 'created_at'], $insertData)->execute();
            }

            if (isset($data['room_id']) && !empty($data['room_id']  && isset($data['professionId']) &&  $data['professionId'] == Profession::ID_NURSE )) {
                foreach ($data['room_id'] as $roomId) {
                    $insertRoomData[] = [
                        'member_id' => $memberModel->id,
                        'room_id' => $roomId,
                        'project_id' => $data['project_id'][0],
                        'operate_id' => $operateId,
                        'created_at' => time(),
                    ];
                }
                Yii::$app->db->createCommand()->batchInsert(UserRoom::tableName(), ['member_id', 'room_id', 'project_id', 'operate_id', 'created_at'], $insertRoomData)->execute();
            }

            if ($memberModel->status == Member::STATUS_INVALID) {
                self::changeCount($memberModel->id);
            }
            $transaction->commit();

            // 删除缓存
            CommonService::baseRedis('member', 2);

        } catch (\Exception $exception) {
            $transaction->rollBack();
            //   $transaction2->rollBack();

            throw new \Exception($exception->getMessage(), 500);
        }

        return ['id' => $memberModel->id];

    }

    /**
     * 编辑用户(基础设置)
     *
     * @param array $params
     * @param int $id
     * @return array
     * @throws \Exception
     */
    public static function updateMember(array $params, int $id)
    {
        $transaction = Yii::$app->db->beginTransaction();
        try {
            // 1.更新用户主表
            $memberModel = Member::findOne($id);
            $old_name = $memberModel->realname;
            $memberModel->realname = $params['name']; // 姓名
            $memberModel->username = $params['user_name']; // 账号
            $memberModel->mobile = $params['mobile']; // 手机号
            $params['password_hash'] && $memberModel->password_hash = $params['password_hash']; // 密码
            $old_status = $memberModel->status;
            $memberModel->status = $params['status']; // 状态
            //     $memberModel->gender = $params['gender']; // 性别

            if (!$memberModel->save()) {
                throw new \Exception('更新人员表数据失败！', 500);
            }

            if ($params['status'] == Member::STATUS_INVALID) {
                AccessTokenService::clearMemberToken($id);
            }

            // 2.更新用户属性
            $memberAttrModel = Attr::find()->where(['member_id' => $id])->all();
            $modelArray = [];
            foreach ($memberAttrModel as $value) {
                $modelArray[$value->project_id] = $value;
            }

            foreach ($params['project_id'] as $project_id) {

                $old_leader = 0;
                if (empty($modelArray[$project_id])) {
                    $model = new Attr;
                    $model->member_id = $memberModel->id;
                    $model->project_id = $project_id;
                    self::addProjectCount($project_id, 1);
                } else {
                    $model = $modelArray[$project_id];
                    $old_leader = $model->is_department_leader;
                    //姓名更新,诊疗室名称更新
                    MemberService::deleteClinic($model->clinic_id, $old_name);
                    MemberService::addClinic($model->clinic_id, $params['name']);
                    unset($modelArray[$project_id]);
                }

                isset($params['professionId']) && !empty($params['professionId']) && $model->profession_id = $params['professionId'];
                isset($params['professionName']) && !empty($params['professionName']) && $model->profession_name = $params['professionName'];
                isset($params['department_id']) && !empty($params['department_id']) && $model->department_id = $params['department_id']; // 部门 id
                $is_department_leader = $params['is_department_leader'] ?? 0;

                if (($old_leader == 1 && $is_department_leader == 2) || ($old_leader == 2 && $is_department_leader == 0) || ($old_leader == 0 && $is_department_leader == 2)) {
                    $model->is_department_leader = $is_department_leader;
                }

                if ($old_leader == 1 && $is_department_leader == 2) { #从部门负责人->项目负责人
                    MemberService::updateDepartmentLeader($model->department_id, $model->member_id);
                }

                // 更新角色，处理用户绑定的项目
                if (!$model->save()) {
                    throw new \Exception('更新人员属性表失败！', 500);
                }


            }

            //删除attr中没有用到的model
            foreach ($modelArray as $value) {
                //删除项目人数
                self::addProjectCount($value->project_id, 2);
                //删除部门人数
                self::addDepartmentCount($value->department_id, 2);
                //删除诊疗室
                MemberService::deleteClinic($value->clinic_id, $old_name);
                //清空 用户项目下客服/医助归属人
                self::clearBelongMember($value->project_id, $value->member_id);

                // 如果在被删除的项目是部门负责人,更新该部门
                if ($value->is_department_leader == 1) {
                    MemberService::updateDepartmentLeader($value->department_id, $value->member_id);
                }
                $value->delete();
            }

            if ($old_status != $params['status']) {

                self::changeCount($memberModel->id);
            }
            $transaction->commit();
            // 删除缓存
            CommonService::baseRedis('member', 2);

        } catch (\Exception $exception) {
            $transaction->rollBack();
            throw new \Exception($exception->getMessage(), 500);
        }
        return ['id' => $id];
    }

    /**
     * 编辑用户(权限-人员)
     *
     * @param array $params
     * @param int $id
     * @return array
     * @throws \Exception
     */
    public static function updateUser(array $params, int $id)
    {
        $transaction = Yii::$app->db->beginTransaction();
        try {
            // 1.更新用户主表
            $memberModel = Member::findOne($id);
            $old_name = $memberModel->realname;
            $memberModel->realname = $params['name']; // 姓名
            $memberModel->username = $params['user_name']; // 账号
            $memberModel->mobile = $params['mobile']; // 手机号
            $params['password_hash'] && $memberModel->password_hash = $params['password_hash']; // 密码
            $old_status = $memberModel->status;
            $memberModel->status = $params['status']; // 状态
            $memberModel->saveAndCheckResult();

            $project_id = $params['project_id'][0];
            // 2.更新用户属性
            $memberAttrModel = Yii::$app->services->attr->findInfo(['member_id' => $id, 'project_id' => $project_id]);
            $old_profession_id = $memberAttrModel->profession_id;
            $old_department_id = $memberAttrModel->department_id;
            isset($params['professionId']) && $memberAttrModel->profession_id = $params['professionId'];
            isset($params['professionName']) && $memberAttrModel->profession_name = $params['professionName'];


            if ($old_department_id != $params['department_id']) {
                self::addDepartmentCount($old_department_id, 2);
                self::addDepartmentCount($params['department_id'], 1);
                self::updateDepartmentLeader($old_department_id, $id);
                self::updateDepartmentLeader($params['department_id'], $id);

                // 判断是不是项目负责人,如果不是,切换部门的时候,变成普通人
                if ($memberAttrModel->is_department_leader != Attr::IS_DEPARTMENT_LEADER_PROJECT) {
                    $memberAttrModel->is_department_leader = Attr::IS_DEPARTMENT_LEADER_NO;
                }
            }
            $memberAttrModel->department_id = $params['department_id'];// 部门 id


            $old_clinic_id = $memberAttrModel->clinic_id;
            $memberAttrModel->profession_id = $params['professionId']; // 岗位id
            $memberAttrModel->profession_name = $params['professionName']; // 岗位 名称
            // 更新诊室姓名
            $memberAttrModel->clinic_id = (string)$params['clinic_id'];
            MemberService::deleteClinic($old_clinic_id, $old_name);
            MemberService::addClinic($params['clinic_id'], $params['name']);

            // 更新角色，处理用户绑定的项目
            $memberAttrModel->saveAndCheckResult();

            // 3.更新用户角色
            if (isset($params['roleIdData']) && !empty($params['roleIdData'])) {
                self::dellUserRole($params['roleIdData'], $id, $project_id); // 更新角色， 处理用户关联表
            }
            if ($old_status != $params['status']) {
                self::changeCount($memberModel->id);
            }

            // 4.更新冗余字段
            $attr = [
                'belong_member_name' => $params['name']
            ];
            User::updateAll($attr, ['belong_member_id' => $id]);

            // 5. 护士岗位 更新治疗室
            if ($params['professionId'] == Profession::ID_NURSE) {
                // 清空用户诊疗室表
                self::dellUserRoom($params['roomIdData'], $id, $project_id); // 更新角色， 处理用户关联表
            } else {
                UserRoom::deleteAll(['member_id' => $id, 'project_id' => $project_id]);
            }

            // 禁用人员时删除归属人ID为当前人员的所有患者归属人
            if ($params['status'] == Member::STATUS_INVALID) {
                self::deleteBelongUser($id);
                // 禁用token
                AccessTokenService::clearMemberToken($id);
            }

            // 修改岗位,清空当前项目下,当前人员患者归属人
            if ($params['professionId'] != $old_profession_id) {
                self::clearBelongMember($project_id,$id);
            }

            $transaction->commit();
            // 删除缓存
            CommonService::baseRedis('member', 2);

        } catch (\Exception $exception) {
            $transaction->rollBack();
            throw new \Exception($exception->getMessage(), 500);
        }
        return ['id' => $id];
    }

    /**
     * 处理用户角色关联表数据
     *
     * @param array $roleIdData
     * @param int $id
     * @throws Exception
     * @author wangxiang
     */
    public static function dellUserRole(array $roleIdData, int $id, $project_id)
    {
        UserRole::deleteAll(['member_id' => $id, 'project_id' => $project_id]);
        $insertData = self::_getUserRoleData($roleIdData, $id, $project_id);
        Yii::$app->db->createCommand()->batchInsert(UserRole::tableName(), ['project_id', 'member_id', 'role_id', 'operate_id', 'created_at'], $insertData)->execute();
    }

    /**
     * 处理用户角色关联表数据
     *
     * @param array $roleIdData
     * @param int $id
     * @throws Exception
     * @throws \yii\db\Exception
     * @author wangxiang
     */
    public static function dellUserRoom(array $roomIdData, int $id, $project_id)
    {
        UserRoom::deleteAll(['member_id' => $id, 'project_id' => $project_id]);
        $insertData = self::_getUserRoomData($roomIdData, $id, $project_id);
        Yii::$app->db->createCommand()->batchInsert(UserRoom::tableName(), ['project_id', 'member_id', 'room_id', 'operate_id', 'created_at'], $insertData)->execute();
    }


    /**
     * 获取新插入人员角色关联表数据
     *
     * @param array $roleIdData
     * @param int $memberId
     * @return array
     * @author wangxiang
     */
    private static function _getUserRoleData(array $roleIdData, int $memberId, $project_id)
    {
        $operateId = Yii::$app->user->identity['member_id'];
        $insertData = [];
        foreach ($roleIdData as $roleId) {
            $insertData[] = [
                'project_id' => $project_id,
                'member_id' => $memberId,
                'role_id' => $roleId,
                'operate_id' => $operateId,
                'created_at' => time(),
            ];
        }

        return $insertData;
    }

    /**
     * 获取新插入人员角色关联表数据
     *
     * @param array $roomIdData
     * @param int $memberId
     * @param $project_id
     * @return array
     * @author wangxiang
     */
    private static function _getUserRoomData(array $roomIdData, int $memberId, $project_id)
    {
        $operateId = Yii::$app->user->identity['member_id'];
        $insertData = [];
        foreach ($roomIdData as $roomId) {
            $insertData[] = [
                'project_id' => $project_id,
                'member_id' => $memberId,
                'room_id' => $roomId,
                'operate_id' => $operateId,
                'created_at' => time(),
            ];
        }

        return $insertData;
    }


    public static function roleList($project_id)
    {
        return Role::find()
            ->select('id as value, name as title')
            ->where(['or', ['project_id' => $project_id], ['type' => Role::TYPE_INLAY]])
            ->andWhere(['status' => Role::STATUS_ENABLE])
            ->asArray()
            ->all();
    }

    /**
     * 添加诊室医生名称
     *
     * @param int $clinic_id
     * @return bool
     */
    public static function addClinic($clinic_id, $name)
    {
        $clinicModel = Clinic::findOne($clinic_id);
        if (!$clinicModel) {
            return false;
        }
        $clinicStr = $clinicModel->clinic_user;
        $clinicArray = $clinicStr ? explode(',', $clinicStr) : [];

        if (!in_array($name, $clinicArray)) {
            $clinicArray[] = $name;
            $clinicStr = implode(',', $clinicArray);
            $clinicModel->clinic_user = $clinicStr;
            $clinicModel->saveAndCheckResult();
        }
        // 删除缓存
        CommonService::baseRedis('clinic', 2);

        return true;
    }

    /**
     * 编辑项目人数
     * @param int type 1 = 添加 2 = 减少
     * @param int $clinic_id
     * @return array
     */
    public static function addProjectCount($project_id, $type)
    {
        $model = Project::findOne($project_id);
        if (!$model) {
            return false;
        }
        if ($type == 1) {
            $model->project_num += 1;
        } else {
            $model->project_num -= 1;
        }

        if ($model->project_num < 0) {
            $model->project_num = 0;
        }

        if ($model->save()) {
            return true;
        }

        return false;

    }

    /**
     * 编辑部门人数
     * @param int type 1 = 添加 2 = 减少
     * @param int $department_id 部门id
     * @return bool
     */
    public static function addDepartmentCount($department_id, $type)
    {
        $model = Department::findOne($department_id);

        if (!$model) {
            return false;
        }
        if ($type == 1) {
            $model->total_num += 1;
        } else {
            $model->total_num -= 1;
        }

        if ($model->total_num < 0) {
            $model->total_num = 0;
        }

        $model->saveAndCheckResult();

        return true;
        /*if ($model->save()) {
            return true;
        }

        return false;*/
    }

    /**
     * 删除之前诊室医生名称
     *
     * @param int $clinic_id
     * @return bool
     */
    public static function deleteClinic($clinic_id, $name)
    {
        $clinicModel = Clinic::findOne($clinic_id);
        if (!$clinicModel) {
            return false;
        }
        $clinicStr = $clinicModel->clinic_user;
        $clinicArray = explode(',', $clinicStr);

        if (in_array($name, $clinicArray)) {
            $clinicArray = array_diff($clinicArray, [$name]);
            $clinicStr = implode(',', $clinicArray);
            $clinicModel->clinic_user = $clinicStr;
            $clinicModel->saveAndCheckResult();
        }
        // 删除缓存
        CommonService::baseRedis('clinic', 2);

        return true;
    }

    /**
     * 权限人员下拉列表
     */
    public static function viewUser($params)
    {
        $id = $params['id'] ?? 0;
        $project_id = $params['project_id'];

        $query = Member::find()
            ->alias('m')
            ->leftJoin(Attr::tableName() . ' attr', 'm.id = attr.member_id')
            ->leftJoin(UserRole::tableName() . ' r', 'm.id = r.member_id and r.project_id = ' . $project_id)
            ->leftJoin(Department::tableName() . ' d', 'd.id = attr.department_id')// 此处以单部门考虑
            ->leftJoin(Clinic::tableName() . ' c', 'c.id = attr.clinic_id')
            ->where(['m.id' => $id])// 确定现在是人员是单个部门
            ->andWhere(['!=', 'm.status', Member::STATUS_DELETE]);
        $query->groupBy('m.id')
            ->select([
                'c.name as clinic_name', 'c.id as clinic_id', 'm.id', 'm.realname as name', 'm.username', 'attr.is_department_leader', 'm.mobile', 'm.gender', 'd.name as department_name', 'attr.profession_id', 'attr.profession_name', new Expression('FROM_UNIXTIME(m.`created_at`, "%Y-%m-%d") created_at'), 'm.status'
                , new Expression('FROM_UNIXTIME(m.`last_time`, "%Y-%m-%d %H：%i") last_time'), 'attr.project_id', 'attr.department_id'
            ]);

        $list = $query
            ->asArray()
            ->one();

        // 角色列表
        $data['roleList'] = Role::find()
            ->select('id as value, name as title')
            ->where(['or', ['project_id' => $project_id], ['type' => Role::TYPE_INLAY]])
            ->andWhere(['status' => Role::STATUS_ENABLE])
            ->asArray()
            ->all();

        // 诊室列表
        $data['clinic'] = Clinic::find()
            ->select('id as value, name as title')
            ->where(['project_id' => $project_id])
            ->andWhere(['status' => Clinic::STATUS_ENABLE])
            ->asArray()
            ->all();

        // 部门
        $data['department'] = Department::find()
            ->select('id as value, name as title')
            ->where(['project_id' => $project_id])
            ->andWhere(['status' => Department::STATUS_ENABLE])
            ->asArray()
            ->all();

        //岗位
        $data['profession'] = Profession::find()
            ->select('id as value, name as title')
            ->andWhere(['status' => Profession::STATUS_ENABLE])
            ->asArray()
            ->all();

        // 治疗室
        $data['clinic_room'] = TreatmentRoom::find()
            ->select('id as value, name as title')
            ->andWhere([
                'status' => Profession::STATUS_ENABLE,
                'project_id' => $project_id
            ])
            ->asArray()
            ->all();

        if (!empty($list)) {
            // 判断角色在不在下拉框的列表中
            $roleIds = array_column($data['roleList'], 'value');
            $list['role'] = MemberService::getRoleIdByMemberId($list['id'], $project_id);
            $list['role'] = array_values(array_intersect($roleIds, $list['role']));
            $list['role_name'] = $list['role'] ? MemberService::getRoleName($list['role']) : [];
            $list['room'] = MemberService::getRoomIdByMemberId($list['id'], $project_id);
            $list['room_name'] = $list['room'] ? MemberService::getRoomName($list['room']) : [];
            $list['mobile'] = $list['mobile'] == 0 ? '' : $list['mobile'];
            $list['profession_id'] = $list['profession_id'] == 0 ? '' : $list['profession_id'];
            $list['department_name'] = $list['department_name'] == null ? '' : $list['department_name'];
            $list['department_id'] = $list['department_id'] == 0 ? '' : $list['department_id'];
        }
        $data['info'] = $list;
        $data['profession_id'] = [Profession::ID_MEDICAL, Profession::ID_CUSTOMER];// 医助、客服ID
        $data['medical_id'] = Profession::ID_MEDICAL;// 医助ID

        return $data;
    }

    /**
     * 改变状态  修改 部门,项目,以及诊室姓名
     * $member_id member表id
     *
     */
    public static function changeCount($member_id)
    {
        $modelArray = Attr::find()->where(['member_id' => $member_id])->all();
        $projectArray = array_column($modelArray, 'project_id');
        $departmentArray = array_column($modelArray, 'department_id');
        $clinicArray = array_column($modelArray, 'clinic_id');

        $project_count = Member::find()
            ->alias('m')
            ->select('a.project_id,count(a.project_id) as count')
            ->leftJoin(Attr::tableName() . 'a', 'a.member_id = m.id')
            ->where(['m.status' => Member::STATUS_ENABLE])
            ->andWhere(['a.project_id' => $projectArray])
            ->groupBy('a.project_id')
            ->asArray()
            ->all();

        $project_diff = array_diff($projectArray, array_column($project_count, 'project_id'));
        // 差集补零
        foreach ($project_diff as $value) {
            $project_count[] = [
                'project_id' => $value,
                'count' => 0,
            ];
        }

        foreach ($project_count as $value) {
            $model = Project::findOne($value['project_id']);
            if (!$model) {
                continue;
            }
            $model->project_num = $value['count'];
            $model->saveAndCheckResult();
        }

        $department_count = Member::find()
            ->alias('m')
            ->select('a.department_id,count(a.department_id) as count')
            ->leftJoin(Attr::tableName() . 'a', 'a.member_id = m.id')
            ->where(['m.status' => Member::STATUS_ENABLE])
            ->andWhere(['a.department_id' => $departmentArray])
            ->groupBy('a.department_id')
            ->asArray()
            ->all();

        $department_diff = array_diff($departmentArray, array_column($department_count, 'department_id'));
        // 差集补零
        foreach ($department_diff as $value) {
            $department_count[] = [
                'department_id' => $value,
                'count' => 0,
            ];
        }

        foreach ($department_count as $value) {
            $model = Department::findOne($value['department_id']);
            if (!$model) {
                continue;
            }
            $model->total_num = $value['count'];
            $model->saveAndCheckResult();
        }

        $clinic_count = Member::find()
            ->alias('m')
            ->select('a.clinic_id,group_concat(m.realname) as count')
            ->leftJoin(Attr::tableName() . 'a', 'a.member_id = m.id')
            ->where(['m.status' => Member::STATUS_ENABLE])
            ->andWhere(['a.clinic_id' => $clinicArray])
            ->groupBy('a.clinic_id')
            ->asArray()
            ->all();

        $clinic_diff = array_diff($clinicArray, array_column($clinic_count, 'clinic_id'));
        // 差集补零
        foreach ($clinic_diff as $value) {
            $clinic_count[] = [
                'clinic_id' => $value,
                'count' => '',
            ];
        }

        foreach ($clinic_count as $value) {
            $model = Clinic::findOne($value['clinic_id']);
            if (!$model) {
                continue;
            }
            $model->clinic_user = $value['count'];
            $model->saveAndCheckResult();
        }

        // 删除缓存
        CommonService::baseRedis('clinic', 2);
        return true;
    }

    /**
     * 更新部门负责人
     *
     * @param $department_id
     * @param null $member_id
     * @return bool
     */
    public static function updateDepartmentLeader($department_id, $member_id = null)
    {
        $query = Member::find()
            ->alias('m')
            ->select('m.realname')
            ->leftJoin(Attr::tableName() . ' a', ' a.member_id = m.id')
            ->where(['and',
                ['m.status' => Member::STATUS_ENABLE],
                ['a.department_id' => $department_id],
                ['a.is_department_leader' => Attr::IS_DEPARTMENT_LEADER_YES]
            ]);

        if ($member_id) {
            $query->andWhere(['!=', 'a.member_id', $member_id]);
        }

        $nameArray = $query->asArray()
            ->all();

        $nameArray = array_column($nameArray, 'realname');
        $nameArray = !empty($nameArray) ? $nameArray : [];
        $departmentModel = Department::findOne($department_id);

        if (!$departmentModel) {
            return false;
        }
        $departmentModel->department_leader = implode(',', $nameArray);
        $departmentModel->saveAndCheckResult();

        return true;
    }

    /**
     * 编辑信息
     *
     * @param MemberForm $model
     * @return array|mixed
     */
    public function updateInfo(MemberForm $model)
    {
        try {
            $transaction = Yii::$app->db->beginTransaction();

            // 用户信息
            $member = $model->getMember();
            $oldImg = $member->head_img;

            // 1.更新基础信息
            $member->realname = $model->realname;
            $member->mobile = $model->mobile;
            $member->gender = $model->gender;
            $member->head_img = $model->head_img;
            $member->save();

            // 2.更新冗余字段
            $attr = [
                'belong_member_name' => $model->realname
            ];
            User::updateAll($attr, ['belong_member_id' => $member->id]);

            // 3.删除原头像
            if ($oldImg && $oldImg != $model->head_img) {
                @unlink(Yii::getAlias('@attachment') . '/' . $oldImg);
            }

            $transaction->commit();

            // 删除缓存
            CommonService::baseRedis('member', 2);

            return ['member_id' => $member->id];
        } catch (\Exception $e) {
            $transaction->rollBack();

            return CommonHelper::api(422, $e->getMessage());
        }
    }

    /**
     * 修改密码
     *
     * @param MemberForm $model
     * @return array|mixed
     */
    public function updatePassword(MemberForm $model)
    {
        try {
            // 用户信息
            $member = $model->getMember();

            // 1.修改密码
            $member->password_hash = Yii::$app->security->generatePasswordHash($model->new_password);
            $member->save();

            return ['member_id' => $member->id];
        } catch (\Exception $e) {
            return CommonHelper::api(422, $e->getMessage());
        }
    }

    /**
     * 绑定绑定
     *
     * @param MemberForm $model
     * @return array|mixed
     */
    public function bindDingtalk(DingtalkForm $model)
    {
        try {
            // 用户信息
            $member = $model->getMember();

            // 1.修改密码
            $member->ding_unionid = $model->ding_unionid;
            $member->ding_openid = $model->ding_openid;
            $member->save();

            return ['member_id' => $member->id];
        } catch (\Exception $e) {
            return CommonHelper::api(422, $e->getMessage());
        }
    }

    /**
     * 禁用人员时删除归属人ID为当前人员的所有患者归属人
     *
     * @param $memberId
     * @return bool
     */
    public static function deleteBelongUser($memberId)
    {
        // 医助归属人
        $patientAssistantIs = User::find()
            ->select('id')
            ->where(['belong_assistant_id' => $memberId])
            ->asArray()
            ->all();

        // 客服归属人
        $patientMemberIs = User::find()
            ->select('id')
            ->where(['belong_member_id' => $memberId])
            ->asArray()
            ->all();

        if ($patientAssistantIs) {
            User::updateAll(['belong_assistant_id' => 0], ['id' => array_column($patientAssistantIs, 'id')]);
        }
        if ($patientMemberIs) {
            User::updateAll(['belong_member_id' => 0, 'belong_member_name' => ''], ['id' => array_column($patientMemberIs, 'id')]);
        }
        return true;
    }

    /**
     * 清空用户,项目下,医助/客服归属人
     * @param $project_id
     * @param $member_id
     */
    public static function clearBelongMember($project_id,$member_id)
    {
        //删除项目 清空客服归属人
        User::updateAll(['belong_member_id' => 0], ['project_id' => $project_id, 'belong_member_id' => $member_id]);
        //删除项目 清空医助归属人
        User::updateAll(['belong_assistant_id' => 0], ['project_id' => $project_id, 'belong_assistant_id' => $member_id]);
    }


}
